#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

#define TEST_MODE 2

#if TEST_MODE == 0

/* alarm + signal */

void sighandler(int signum)
{
	if(signum == SIGALRM)
	{
		//隔5s后发送一次SIGALRM信号
		if(alarm(1) == -1)
			perror("alarm");
		printf("receive SIGALRM signal\r\n");
	}
}

int main(int argv, char *argc[])
{
	//注册信号处理函数
	if(signal(SIGALRM, sighandler) == SIG_ERR)
	{
		perror("signal");
		return -1;
	}
	//隔5s后发送一次SIGALRM信号
	if(alarm(1) == -1)
	{
		perror("alarm");
		return -1;
	}
	while(1)
	{
		//此处的sleep系统调用可能会被信号打断
		sleep(5);
	}
}

#elif TEST_MODE == 1
/* setitimer + sigaction */

void sighandler(int signum, siginfo_t *siginfo, void *p)
{
	if(signum == SIGALRM)
		printf("receive SIGALRM signal\r\n");
}

int main(int argc, char *argv[])
{
	struct itimerval currValue;
	struct sigaction act;
	
	//获取之前的信号处理方式
	if(sigaction(SIGALRM, NULL, &act) == -1)
	{
		perror("sigaction");
		return -1;
	}
	//修改之前的信号处理方式
	act.sa_sigaction = sighandler;
	act.sa_flags = SA_SIGINFO;
	if(sigaction(SIGALRM, &act, NULL) == -1)
	{
		perror("sigaction");
		return -1;
	}
	
	//定时器周期
	currValue.it_interval.tv_sec = 1;
	currValue.it_interval.tv_usec = 0;
	//第一次超时时间
	currValue.it_value.tv_sec = 1;
	currValue.it_value.tv_usec = 0;
	//设置一个周期定时器
	if(setitimer(ITIMER_REAL, &currValue, NULL) == -1)
	{
		perror("setitimer");
		return -1;
	}
	
	while(1)
	{
		//此处的sleep系统调用可能会被信号打断
		sleep(5);
	}
}

#elif TEST_MODE == 2
/* 信号集 */

int main(int argc, char *argv[])
{
	sigset_t sigs;
	
	//清空信号集
	if(sigemptyset(&sigs) == -1)
	{
		perror("sigemptyset");
		return -1;
	}
	//向信号集添加SIGALRM信号
	if(-1 == sigaddset(&sigs, SIGALRM))
	{
		perror("sigaddset");
		return -1;
	}
	//修改阻塞信号集，将上面设置的SIGALRM追加到阻塞信号集中
	if(sigprocmask(SIG_BLOCK, &sigs, NULL) == -1)
	{
		perror("sigprocmask");
		return -1;
	}
	
	//向当前进程发送SIGALRM信号
	if(kill(getpid(), SIGALRM) == -1)
	{
		perror("kill");
		return -1;
	}
	
	//获取到达而未处理的信号的信号集
	if(sigpending(&sigs) == -1)
	{
		perror("sigpending");
		return -1;
	}
	//判断SIGALRM信号是否在信号集中，SIGALRM信号已经被阻塞，所以暂时不能被处理
	if(sigismember(&sigs, SIGALRM) == 1)
		printf("SIGALRM is set\r\n");
	else
		printf("SIGALRM is not set\r\n");
	
	//清空信号集
	if(sigemptyset(&sigs) == -1)
	{
		perror("sigemptyset");
		return -1;
	}
	//向信号集添加SIGALRM信号
	if(sigaddset(&sigs, SIGALRM) == -1)
	{
		perror("sigaddset");
		return -1;
	}
	//修改屏蔽信号集，将上面设置的SIGALRM从阻塞信号集中清除
	//这里清除了对信号SIGALRM的阻塞，所以信号会立即相应，由于SIGALRM默认终止进程，所以调用此函数后进程会被终止
	if(sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1)
	{
		perror("sigprocmask");
		return -1;
	}
	
	//以下代码不会被执行
	while(1)
	{
		sleep(5);
		printf("signal test\r\n");
	}
}

#endif